package com.wlz.controller;

import com.wlz.model.Article;
import com.wlz.resp.JsonResult;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchHitsImpl;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author： wlz
 * @Date 2020/12/23 18:43
 * @description： TODO
 * @version: 1.0
 */

@RestController
@RequestMapping("articleRestTemplate")
public class ArticleRestTemplateController {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 分页查询
     * @param currentPage
     * @param limit
     * @return
     */
    @GetMapping("list")
    public JsonResult list(@RequestParam("currentPage") Integer currentPage, @RequestParam("limit") Integer limit) {
        if (currentPage == null || currentPage < 0 || limit == null || limit <= 0) {
            return new JsonResult(false, "请输入合法的分页参数");
        }
        // 分页列表查询
        // 旧版本的 Repository 中的 search 方法被废弃了。
        // 这里采用 ElasticSearchRestTemplate 或 ElasticsearchOperations 来进行分页查询

        JsonResult jsonResult = new JsonResult(true);
        NativeSearchQuery query = new NativeSearchQuery(new BoolQueryBuilder());
        query.setPageable(PageRequest.of(currentPage, limit));

        // 方法1：
        SearchHits<Article> searchHits = elasticsearchRestTemplate.search(query, Article.class);

        // 方法2：
        // SearchHits<Article> searchHits = elasticsearchOperations.search(query, Article.class);

        // 方法3：
        // 在方法上加 @Query 注解，其中手写查询语句 —— 有点难度，不会写

        List<Article> articles = searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        jsonResult.put("count", searchHits.getTotalHits());
        jsonResult.put("articles", articles);
        return jsonResult;
    }

    /**
     *  滚动查询数据
     * @param scrollId
     * @param size
     * @return
     */
    @GetMapping("scroll")
    public JsonResult scroll(String scrollId, Integer size) {
        // 滚动查询 scroll api
        if (size == null || size <= 0) {
            return new JsonResult(false, "请输入每页查询数");
        }
        NativeSearchQuery query = new NativeSearchQuery(new BoolQueryBuilder());
        query.setPageable(PageRequest.of(0, size));
        SearchHits<Article> searchHits = null;
        if (StringUtils.isEmpty(scrollId)) {
            // 开启一个滚动查询，设置该 scroll 上下文存在 60s
            // 同一个 scroll 上下文，只需要设置一次 query（查询条件）
            searchHits = elasticsearchRestTemplate.searchScrollStart(60000, query, Article.class, IndexCoordinates.of("article"));
            if (searchHits instanceof SearchHitsImpl) {
                scrollId = ((SearchHitsImpl) searchHits).getScrollId();
            }
        } else {
            // 继续滚动
            searchHits = elasticsearchRestTemplate.searchScrollContinue(scrollId, 60000, Article.class, IndexCoordinates.of("article"));
        }

        List<Article> articles = searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        if (articles.size() == 0) {
            // 结束滚动
            elasticsearchRestTemplate.searchScrollClear(Collections.singletonList(scrollId));
            scrollId = null;
        }

        if (scrollId == null) {
            return new JsonResult(false, "已到末尾");
        } else {
            JsonResult jsonResult = new JsonResult(true);
            jsonResult.put("count", searchHits.getTotalHits());
            jsonResult.put("size", articles.size());
            jsonResult.put("articles", articles);
            jsonResult.put("scrollId", scrollId);
            return jsonResult;
        }

    }

}
